package com.iceframework.core.task.service;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ThreadPoolExecutor;

import com.iceframework.core.task.abs.ITaskPoolExeutor;
import com.iceframework.core.task.constants.TaskConstants;
import com.iceframework.core.task.entity.TaskInfoEntity;
import com.iceframework.core.task.exception.TaskNumberOverflowException;
import com.iceframework.core.thread.utils.ThreadPoolDispatcherUtils;
import com.iceframework.core.utils.KeyUtils;

/**
 * 
 * 任务池执行类
 * @author Palo
 *
 */
public class TaskPoolExecutor implements ITaskPoolExeutor {

	// 待执行任务队列
	private ConcurrentSkipListMap<String, TaskInfoEntity> pendingTaskQueueMap = null;
	// 执行中队列
	private ConcurrentSkipListMap<String, TaskInfoEntity> executingTaskQueueMap = null;
	// 执行完成队列
//	private ConcurrentSkipListMap<String, TaskInfoEntity> doneTaskQueueMap = null;
	// 待执行任务队列
	private Queue<String> pendingTaskQueue = null;
	
	// 最大排队任务数(-1无上限)
	private int maxPendingQueueSize = -1;
	// 最大任务执行(默认值1)
	private int maxExecuteTaskSize = 1;

	private ThreadPoolExecutor threadPoolExecutor = null;
	
	private ThreadPoolExecutor mainThreadPoolExecutor = null;

	public int executingTask = 0;

	private boolean globalExecuteFlag = false;
	private boolean globalDestoryFlag = false;

	public TaskPoolExecutor() {
		mainThreadPoolExecutor = ThreadPoolDispatcherUtils.mallocThreadPool(this.getClass(), "main-thread" ,10);
		pendingTaskQueueMap = new ConcurrentSkipListMap<String, TaskInfoEntity>();
		executingTaskQueueMap = new ConcurrentSkipListMap<String, TaskInfoEntity>();
//		doneTaskQueueMap = new ConcurrentSkipListMap<String, TaskInfoEntity>();
		pendingTaskQueue = new LinkedList<String>();
	}

	public TaskPoolExecutor(int maxExecuteTaskSize) {
		mainThreadPoolExecutor = ThreadPoolDispatcherUtils.mallocThreadPool(this.getClass(), "main-thread" ,10);
		this.maxExecuteTaskSize = maxExecuteTaskSize;
		pendingTaskQueueMap = new ConcurrentSkipListMap<String, TaskInfoEntity>();
		executingTaskQueueMap = new ConcurrentSkipListMap<String, TaskInfoEntity>();
//		doneTaskQueueMap = new ConcurrentSkipListMap<String, TaskInfoEntity>();
		pendingTaskQueue = new LinkedList<String>();
	}
	
	public TaskPoolExecutor(int maxExecuteTaskSize,int maxPendingQueueSize) {
		mainThreadPoolExecutor = ThreadPoolDispatcherUtils.mallocThreadPool(this.getClass(), "main-thread" ,10);
		this.maxExecuteTaskSize = maxExecuteTaskSize;
		this.maxPendingQueueSize = maxPendingQueueSize;
		pendingTaskQueueMap = new ConcurrentSkipListMap<String, TaskInfoEntity>();
		executingTaskQueueMap = new ConcurrentSkipListMap<String, TaskInfoEntity>();
//		doneTaskQueueMap = new ConcurrentSkipListMap<String, TaskInfoEntity>();
		pendingTaskQueue = new LinkedList<String>();
	}

	private void doTask() {
		mainThreadPoolExecutor.execute(new Runnable() {
			@Override
			public void run() {
				try {
					while (globalDestoryFlag) {
						while (globalExecuteFlag) {
							if (threadPoolExecutor == null || threadPoolExecutor.isTerminated()) {
								System.out.println("暂停执行任务");
								Thread.sleep(1000);
								continue;
							}
							List<String> keySet2 = new ArrayList<String>(executingTaskQueueMap.keySet());
							for (String key : keySet2) {
								TaskInfoEntity taskInfoEntity = executingTaskQueueMap.get(key);
								if (taskInfoEntity != null && TaskConstants.TASK_STATUS_PENDING.equals(taskInfoEntity.getStatus())) {
									executingTask++;
									taskInfoEntity.setStatus(TaskConstants.TASK_STATUS_EXECTUTING);
									threadPoolExecutor.execute(new Runnable() {
										@Override
										public void run() {
											try {
												taskInfoEntity.doTask();
												System.out.println("执行任务完成"+taskInfoEntity.getName());
											} catch (Exception e) {
												e.printStackTrace();
											} finally {
												taskInfoEntity.setStatus(TaskConstants.TASK_STATUS_EXECTUTED);
												executingTaskQueueMap.remove(key);
												executingTask--;
											}
										}
									});
								}
								Thread.sleep(100);
							}
						}
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
					onStop();
				}
			}
		});

	}

	private void putToExecutingTask() {
		mainThreadPoolExecutor.execute(new Runnable() {
			@Override
			public void run() {
				while (globalDestoryFlag) {
					while (globalExecuteFlag) {
						if(pendingTaskQueue.size()==0) {
							try {
								Thread.sleep(1000);
							} catch (InterruptedException e) {
							}
							continue;
						}
						int pendingTaskQueueCount = pendingTaskQueueMap.keySet().size();
						int execTaskQueueCount = executingTaskQueueMap.keySet().size();
						if(pendingTaskQueue.size() >0) {
							if (pendingTaskQueueCount >= 0 && execTaskQueueCount <= maxExecuteTaskSize) {
								String key = pendingTaskQueue.poll();
								TaskInfoEntity taskInfoEntity = pendingTaskQueueMap.get(key);
								pendingTaskQueue.remove(key);
								pendingTaskQueueMap.remove(key);
								executingTaskQueueMap.put(key, taskInfoEntity);
							}
						}
					}
				}

			}
		});

	}

	@Override
	public void onStart() {
		System.out.println("启动任务池");
		globalExecuteFlag = true;
		globalDestoryFlag = true;
		threadPoolExecutor = ThreadPoolDispatcherUtils.mallocThreadPool(this.getClass(), "doTask", maxExecuteTaskSize);
		putToExecutingTask();
		doTask();
	}

	@Override
	public void onPause() {
		globalExecuteFlag = false;
		System.out.println("暂停任务池");
	}

	@Override
	public void onStop() {
		globalExecuteFlag = false;
		globalDestoryFlag = false;
		cleanTask();
		threadPoolExecutor.shutdownNow();
		while (threadPoolExecutor.isTerminated()) {
			System.out.println("终止任务中...");
			break;
		}
		System.out.println("终止任务完成");
		System.out.println("停止任务池");
		threadPoolExecutor = ThreadPoolDispatcherUtils.mallocThreadPool(this.getClass(), "doTask", maxExecuteTaskSize);
	}
	
	@Override
	public void onDestory() {
		globalExecuteFlag = false;
		globalDestoryFlag = false;
		System.out.println("销毁任务池");
		cleanTask();
		if(threadPoolExecutor != null) {
			threadPoolExecutor.shutdown();
		}
		if(mainThreadPoolExecutor != null) {
			mainThreadPoolExecutor.shutdown();
		}
		
	}

	public synchronized void addTask(TaskInfoEntity taskInfoEntity) throws TaskNumberOverflowException {
		int pendingTaskQueueSize = pendingTaskQueueMap.keySet().size();
		if (maxPendingQueueSize == -1 || pendingTaskQueueSize + 1 <= maxPendingQueueSize) {
			String key = KeyUtils.genUUID();
			taskInfoEntity.setTaskId(key);
			taskInfoEntity.setStatus(TaskConstants.TASK_STATUS_PENDING);
			pendingTaskQueueMap.put(key, taskInfoEntity);
			pendingTaskQueue.offer(key);
		} else {
			throw new TaskNumberOverflowException(maxPendingQueueSize);
		}
	}

	private void cleanTask() {
		pendingTaskQueueMap = new ConcurrentSkipListMap<String, TaskInfoEntity>();
		executingTaskQueueMap = new ConcurrentSkipListMap<String, TaskInfoEntity>();
//		doneTaskQueueMap = new ConcurrentSkipListMap<String, TaskInfoEntity>();
		pendingTaskQueue = new LinkedList<String>();
	}

}
